package se.webbzon.boltzmann.minigame.botany;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;

import se.webbzon.boltzmann.camera.AbstractCamera;
import se.webbzon.boltzmann.configuration.Difficulty;
import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.boltzmann.environment.DefaultEnvironment;
import se.webbzon.boltzmann.input.Input;
import se.webbzon.boltzmann.minigame.InfoBar;
import se.webbzon.boltzmann.minigame.Puzzle;
import se.webbzon.boltzmann.minigame.Chronograph;
import se.webbzon.boltzmann.minigame.ScoreBar;
import se.webbzon.boltzmann.minigame.effect.SandBoxCloud;
import se.webbzon.boltzmann.minigame.effect.SandBoxRain;
import se.webbzon.boltzmann.minigame.effect.SandBoxSun;
import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBoxContainer;
import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBox;
import se.webbzon.boltzmann.minigame.sandbox.SandBox;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxArrow;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxCursor;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxInfo;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxScore;
import se.webbzon.boltzmann.sound.SoundUtils;
import se.webbzon.boltzmann.world.DefaultWorldLoader;
import se.webbzon.oschi01.utilities.ArrayUtils;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldView;

public class BotanyGame extends Puzzle {
	
	// The available cycles
	private Cycle[] cycles = {
			new CarbonCycle(),
			new NitrogenCycle(),
			new OzoneCycle(),
			new PhosphorusCycle(),
			new PhotosynthesisCycle(),
			new SulfurCycle()
	};
	
	// The current cycle and its index
	private Cycle current;
	private int index;
	
	/*============================================================
	Constructors
	============================================================*/

	public BotanyGame() {
		super("puzzles/botany");
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override
	protected WorldArea loadPuzzle(WorldView view, Input input) {
		try {
			DefaultEnvironment env = new DefaultEnvironment();
			DefaultWorldLoader loader = new DefaultWorldLoader(env,"euler/r102");
			WorldArea world = loader.load();
			//DummyCamera camera = new DummyCamera();
			//camera.addView(view);
			//world.createInstance(camera);
			world.findInstances(AbstractCamera.class).iterator().next().addView(view);
			
			//box.addItem(container);
			return world;
		} catch (Exception e) {
			Debug.report(e);
			return null;
		}
	}

	@Override protected void loadSandBox(DefaultSandBox box) {
		index = 0;
		shuffle(cycles);
		Rectangle r = new Rectangle();
		box.getBoundary(r);
		SandBoxScore score = new SandBoxScore();
		box.setScore(score);
		SandBoxInfo info = new SandBoxInfo("Pick up molecules with the action button");
		box.setInfo(info);
		
		ScoreBar scoreBar = new ScoreBar(false);
		scoreBar.addCheckpoint(1000);
		scoreBar.addCheckpoint(2000);
		scoreBar.addCheckpoint(5000);
		box.addItem(scoreBar);
		
		InfoBar infoBar = new InfoBar();
		box.addItem(infoBar);
		
		Chronograph cr = new Chronograph();
		cr.reset(40 * 60);
		cr.setSpeed(-1);
		box.addItem(cr);
		
		SandBoxCursor cursor = new SandBoxCursor();
		box.addItem(cursor);
		
		CycleListenerImpl listener = new CycleListenerImpl(box);
		current = cycles[index++];
		current.addListener(listener);
		box.addItem(current);
	}

	@Override
	protected void onBegin(WorldArea world) {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onEnd(WorldArea world) {
		// TODO Auto-generated method stub
		
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Shuffles the provided array of cycles such that the cycle
	 * will appear in increasing difficulty. **/
	private final void shuffle(Cycle[] cycles) {
		ArrayList<ArrayList<Cycle>> divided = new ArrayList<ArrayList<Cycle>>();
		Difficulty[] diffs = Difficulty.values();
		for (int d = 0; d < diffs.length; d++) {
			divided.add(new ArrayList<Cycle>());
		}
		for (Cycle cycle : cycles) {
			divided.get(cycle.getDifficulty().ordinal()).add(cycle);
		}
		int offset = 0;
		for (int d = 0; d < diffs.length; d++) {
			Cycle[] shuffled = divided.get(d).toArray(new Cycle[0]);
			ArrayUtils.shuffle(shuffled);
			System.arraycopy(shuffled, 0, cycles, offset, shuffled.length);
			offset += shuffled.length;
		}
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class CycleListenerImpl implements CycleListener {
		
		private final SandBox box;
		
		public CycleListenerImpl(SandBox box) {
			this.box = box;
		}

		@Override public void onComplete(Cycle c) {
			SoundUtils.playSound("success");
			c.removeListener(this);
			box.removeItem(c);
			if (index < cycles.length) {
				current = cycles[index++];
				current.addListener(this);
				box.addItem(current);
			} else {
				System.out.println("Complete!");
			}
		}
		
	}

}
